#    pythonequations is a collection of equations expressed as Python classes
#    Copyright (C) 2008 James R. Phillips
#    2548 Vera Cruz Drive
#    Birmingham, AL 35235 USA
#    email: zunzun@zunzun.com
#
#    License: BSD-style (see LICENSE.txt in main source directory)
#    Version info: $Id: __init__.py 267 2010-09-25 13:25:43Z zunzun.com $

import pythonequations, pythonequations.EquationBaseClasses, pythonequations.ExtraCodeForEquationBaseClasses, pythonequations.EquationsForPolyfunctionals
import numpy
numpy.seterr(all = 'raise') # numpy raises warnings, convert to exceptions to trap them


class Polyrational2D(pythonequations.EquationBaseClasses.Equation2D):
    RequiresAutoGeneratedGrowthAndDecayForms = False
    RequiresAutoGeneratedOffsetForm = True
    RequiresAutoGeneratedReciprocalForm = False
    RequiresAutoGeneratedInverseForms = False
    _name = "User-Selectable Rational"
    _HTML = "y = user-selectable rational"
    coefficientDesignatorTuple = ()
    polyrationalFlag = 1
    EquationListForPolyrational = pythonequations.EquationsForPolyfunctionals.GenerateListForPolyrationals('x', 'x_in')
    Polyrat2DEqList = pythonequations.EquationsForPolyfunctionals.GenerateListForPolyrationals('unused', 'unused')
    # reusing temp_x_sq and temp_y_sq
    function_cpp_code = 'int indexStart, indexEnd;'
    function_cpp_code += 'temp = 0.0;\ntemp_x_sq = 0.0;\ntemp_y_sq = 0.0;\n'
    function_cpp_code += 'indexStart = 0;\nindexEnd = _pndia[0];\n'
    function_cpp_code += 'for (int k=indexStart; k<indexEnd; k++)\n\ttemp_x_sq += coeff[k] * _id[_cwo[k]+i];\n'
    function_cpp_code += 'indexStart = _pndia[0];\nindexEnd = _pndia[1];\n'
    function_cpp_code += 'for (int k=indexStart; k<indexEnd; k++)\n\ttemp_y_sq += coeff[k] * _id[_cwo[k]+i];\n'
    function_cpp_code += 'temp = temp_x_sq / (1.0 + temp_y_sq);\n'
    function_cpp_code += 'if (_nc == (1 + _pndia[1])) // any offset?\n'
    function_cpp_code += 'temp = temp + coeff[_nc - 1];\n'


    def CreateCacheGenerationList(self):
        self.CacheGenerationList = []
        for i in range(len(self.EquationListForPolyrational)):
            if i in self.Polyrat2DNumeratorFlags:
                self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Polyrational2D(NameOrValueFlag=1, args=i), i])
        for i in range(len(self.EquationListForPolyrational)):
            if i in self.Polyrat2DDenominatorFlags:
                self.CacheGenerationList.append([pythonequations.ExtraCodeForEquationBaseClasses.CG_Polyrational2D(NameOrValueFlag=1, args=i), i])

    def SpecificCodeCPP(self):
        coeffCount = 0
        s = ""
        s += '\tdouble numerator = 0.0;\n'
        s += '\tdouble denominator = 0.0;\n'
        for i in range(len(self.EquationListForPolyrational)):
            if i in self.Polyrat2DNumeratorFlags:
                if i == 0:
                    s += "\tnumerator += " + self.coefficientDesignatorTuple[coeffCount] + ";\n"
                else:
                    s += "\tnumerator += " + self.coefficientDesignatorTuple[coeffCount] + " * " + self.EquationListForPolyrational[i].CPP + ";\n"
                coeffCount += 1
        for i in range(len(self.EquationListForPolyrational)):
            if i in self.Polyrat2DDenominatorFlags:
                if i == 0:
                    s += "\tdenominator += " + self.coefficientDesignatorTuple[coeffCount] + ";\n"
                else:
                    s += "\tdenominator += " + self.coefficientDesignatorTuple[coeffCount] + " * " + self.EquationListForPolyrational[i].CPP + ";\n"
                coeffCount += 1
        s += "\ttemp = numerator / (1.0 + denominator);\n"
        return s


    def Initialize(self):
        self.coefficientDesignatorTuple = ()
        self.additionalDesignatorList = []

        _HTML = "y = user-selectable rational"
        if len(self.Polyrat2DNumeratorFlags) == 0 or len(self.Polyrat2DDenominatorFlags) == 0:
            if self.extendedName == '':
                return
            if self.extendedName == 'Offset':
                clist = list(self.coefficientDesignatorTuple)
                self.additionalDesignatorList.append('Offset')
                clist.append('Offset')
                self.coefficientDesignatorTuple = tuple(clist)
                return
        
        for i in range(len(self.Polyrat2DNumeratorFlags) + len(self.Polyrat2DDenominatorFlags)):
            self.coefficientDesignatorTuple += (pythonequations.EquationBaseClasses.Equation.ascii[i]),
                
        self.CannotAcceptDataWithZeroX = False
        self.CannotAcceptDataWithPositiveX = False
        self.CannotAcceptDataWithNegativeX = False
        for i in range(len(self.Polyrat2DNumeratorFlags)):
            self.CannotAcceptDataWithZeroX |= self.EquationListForPolyrational[self.Polyrat2DNumeratorFlags[i]].CannotAcceptDataWithZeroX
            self.CannotAcceptDataWithPositiveX |= self.EquationListForPolyrational[self.Polyrat2DNumeratorFlags[i]].CannotAcceptDataWithPositiveX
            self.CannotAcceptDataWithNegativeX |= self.EquationListForPolyrational[self.Polyrat2DNumeratorFlags[i]].CannotAcceptDataWithNegativeX
        for i in range(len(self.Polyrat2DDenominatorFlags)):
            self.CannotAcceptDataWithZeroX |= self.EquationListForPolyrational[self.Polyrat2DDenominatorFlags[i]].CannotAcceptDataWithZeroX
            self.CannotAcceptDataWithPositiveX |= self.EquationListForPolyrational[self.Polyrat2DDenominatorFlags[i]].CannotAcceptDataWithPositiveX
            self.CannotAcceptDataWithNegativeX |= self.EquationListForPolyrational[self.Polyrat2DDenominatorFlags[i]].CannotAcceptDataWithNegativeX

        self._HTML = "</B><B>y = (" # turn off any preceding bolding
        count = 0
        for xindex in range(len(self.EquationListForPolyrational)):
            if xindex in self.Polyrat2DNumeratorFlags: # numerator
                if self.EquationListForPolyrational[xindex]._HTML == '':
                    self._HTML += pythonequations.EquationBaseClasses.Equation.ascii[count] + " "
                else:
                    self._HTML += pythonequations.EquationBaseClasses.Equation.ascii[count] + "(</B>&nbsp;" + self.EquationListForPolyrational[xindex]._HTML + "&nbsp;<B>) "
                count += 1
                if len(self.Polyrat2DNumeratorFlags) > count:
                    self._HTML += "+ "
        self._HTML += ") / (1.0 + "
        count = 0
        for xindex in range(len(self.EquationListForPolyrational)):
            if xindex in self.Polyrat2DDenominatorFlags: # denominator
                if self.EquationListForPolyrational[xindex]._HTML == '':
                    self._HTML += pythonequations.EquationBaseClasses.Equation.ascii[count + len(self.Polyrat2DNumeratorFlags)] + " "
                else:
                    self._HTML += pythonequations.EquationBaseClasses.Equation.ascii[count + len(self.Polyrat2DNumeratorFlags)] + "(</B>&nbsp;" + self.EquationListForPolyrational[xindex]._HTML + "&nbsp;<B>) "
                count += 1
                if len(self.Polyrat2DDenominatorFlags) > count:
                    self._HTML += "+ "
        self._HTML += ')</B>'

        pythonequations.EquationBaseClasses.Equation2D.Initialize(self)
